/*

	Example: Zooming in Flash
	
	Author:
	Daniel Gasienica
	daniel@gasienica.ch
	http://gasi.ch/
	
	
	Originally published on
	http://gasi.ch/blog/2008/02/05/zooming-in-flash-flex/
	
	Released under the
	Creative Commons Attribution-Share Alike License
	http://creativecommons.org/licenses/by-sa/3.0/
	
*/
package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.ui.Keyboard;


	public class ZoomCanvas extends Sprite
	{
		private var affineTransform : Matrix
		
		// Constructor
		public function ZoomCanvas()
		{
			addEventListener( Event.ADDED_TO_STAGE, registerListeners )
			createGrid()
		}
		
		
		// Transformations
		public function scaleAt( scale : Number, originX : Number, originY : Number ) : void
		{
			// get the transformation matrix of this object
			affineTransform = transform.matrix
			
			
			// move the object to (0/0) relative to the origin
			affineTransform.translate( -originX, -originY )
			
			// scale
			affineTransform.scale( scale, scale )
			
			// move the object back to its original position
			affineTransform.translate( originX, originY )
			
			
			// apply the new transformation to the object
			transform.matrix = affineTransform
		}
		
		public function rotateAt( angle : Number, originX : Number, originY : Number ) : void
		{
			// get the transformation matrix of this object
			affineTransform = transform.matrix


			// move the object to (0/0) relative to the origin
			affineTransform.translate( -originX, -originY )
			
			// rotate
			affineTransform.rotate( angle )
			
			// move the object back to its original position
			affineTransform.translate( originX, originY )


			// apply the new transformation to the object
			transform.matrix = affineTransform
		}
		
		
		// Helpers
		private function registerListeners( event : Event ) : void
		{
			// Panning
			stage.addEventListener( MouseEvent.MOUSE_DOWN, onMouseDown )
			stage.addEventListener( MouseEvent.MOUSE_UP, onMouseUp )
			
			// Mouse wheel support for zooming
			stage.addEventListener( MouseEvent.MOUSE_WHEEL, onMouseWheel )
			
			// Keyboard support for zooming
			stage.addEventListener( KeyboardEvent.KEY_DOWN, onKeyDown )			
		}
		
		private function createGrid() : void
		{
			var spacing : Number = 10
			
			for( var row : uint = 0; row < 5; row++ )
			{
				for( var column : uint = 0; column < 5; column++ )
				{
					var circle : Circle = new Circle()
					
					circle.x = column * ( circle.width + spacing )
					circle.y = row * ( circle.height + spacing )
					
					addChild( circle )
				}
			}	
		}
		
		
		// Event Handlers
		private function onMouseWheel( event : MouseEvent ) : void
		{
			// set the origin of the transformation
			// to the current position of the mouse
			var originX : Number = stage.mouseX
			var originY : Number = stage.mouseY
			
			// zoom
			if( !event.altKey )
			{
				if( event.delta > 0 )
				{					
					// zoom in
					scaleAt( 6/5, originX, originY ) 
				}
				else
				{
					// zoom out					
					scaleAt( 5/6, originX, originY )
				}
			}
			else
			{
				// rotate
				rotateAt( event.delta / 20, originX, originY )
			}
		}
		
		private function onMouseDown( event : MouseEvent ) : void
		{
			startDrag()
		}
		
		private function onMouseUp( event : MouseEvent ) : void
		{
			stopDrag()
		}
		
		/**
		 * Keyboard support for zooming due to
		 * missing mouse wheel support on Mac OS
		 */
		private function onKeyDown( event : KeyboardEvent ) : void
		{
			// set the origin of the transformation
			// to the current position of the mouse
			var originX : Number = stage.mouseX
			var originY : Number = stage.mouseY
		
			// zoom
			if( event.keyCode == Keyboard.UP )
			{
				// zoom in
				scaleAt( 6/5, originX, originY )							
			}
			else if( event.keyCode == Keyboard.DOWN )
			{
				// zoom out
				scaleAt( 5/6, originX, originY )					
			}
			// rotate
			else if( event.keyCode == Keyboard.LEFT )
			{
				 // rotate left	
				rotateAt( -Math.PI / 60, originX, originY )				
			}
			else if( event.keyCode == Keyboard.RIGHT )
			{
				 // rotate right
				rotateAt( Math.PI / 60, originX, originY )				
			}
		}
	}	
}